package com.suarte.core.hibernate;

import com.suarte.core.Company;
import com.suarte.core.Contact;
import com.suarte.core.Quotation;
import com.suarte.core.QuotationDetail;
import com.suarte.core.QuotationStatus;
import com.suarte.core.dao.QuotationDao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.appfuse.dao.hibernate.GenericDaoHibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @date   Dec 20, 2010
 * @author Ggutierrez
 */
@Repository("quotationDao")
public class QuotationDaoHibernate extends GenericDaoHibernate<Quotation, Long> implements QuotationDao {
    private int maxResults;

    public QuotationDaoHibernate() {
        super(Quotation.class);
    }

    public void setMaxResults(int maxResults) {
        this.maxResults = maxResults;
    }        

    public List<Quotation> findByDescription(String description) {
        return getHibernateTemplate().find("from Quotation where description like upper(?)", description.concat("%").toUpperCase());
    }

    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void store(Quotation object) {
        getHibernateTemplate().saveOrUpdate(object);
    }

    @Override
    public Quotation get(Long id) {
        List<Quotation> results = getHibernateTemplate().find("from Quotation this join fetch this.details where this.id = ?", id);
        return !results.isEmpty() ? results.get(0) : null;
    }

    public void deleteDetails(List<QuotationDetail> args) {
        getHibernateTemplate().deleteAll(args);
    }

    public List<Quotation> findQuotations(Long id, String description, Date date, Company company, Contact contact, QuotationStatus status) {
        String hql = "from Quotation this join fetch this.contact contact join fetch this.company company "
                + " where 1 = 1";
        List args = new ArrayList();

        if (id != null) {
            args.add(id);
            hql += " and this.id = ?";
        }
        if (!isBlank(description)) {
            args.add(description.toUpperCase().concat("%"));
            hql += " and upper(ltrim(rtrim(this.description))) like upper(ltrim(rtrim(?)))";
        }
        if (date != null) {
            args.add(date);
            hql += " and this.transDate = ?";
        }

        if (company != null) {
            args.add(company);
            hql += " and company = ?";
        }

        if (contact != null) {
            args.add(contact);
            hql += " and contact = ?";
        }

        if (status != null) {
            args.add(status);
            hql += " and this.status = ?";
        }

        List results = find(hql, args.toArray(), 50);
        return results;
    }

    private boolean isBlank(String value) {
        return value == null || value.trim().length() == 0;
    }
    
    public List find(final String hql, final Object[] args, final int maxResults) {
        HibernateCallback callback = new HibernateCallback() {

            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(hql);
                if (maxResults > 0) {
                    query.setMaxResults(maxResults);
                }
                if (args != null) {
                    for (int i = 0; i < args.length; i++) {
                        query.setParameter(i, args[i]);
                    }
                }
                return query.list();
            }
        };
        return (List) getHibernateTemplate().execute(callback);
    }
}
